/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Sueca;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Random;

/**
 *
 * @author Administrador
 */
public class Mesa {

    private Jogador m_j0;
    private Jogador m_j1;
    private Jogador m_j2;
    private Jogador m_j3;

    private IA JogadorIA;

    private Baralho m_baralho;
    private Carta m_trunfo;

    private Jogador m_jogadores[];
    private Jogador m_D1[];
    private Jogador m_D2[];

    Jogo m_jogo;
    Partida m_partida;
    Rodada m_rodada;

    private MaquinaRegra m_regras;

    private int m_opcao;
    
    private static Mesa instance;

    Carta[] cartasMesa = new Carta[40];
    private Integer numCrtsMesa = 0;
    private Integer numCrtsRodada = 0;
//    Carta[] cartasRodada = new Carta[4];

    private Mesa(){
        
    }

    public static Mesa getInstance(){
        if(instance == null){
            instance = new Mesa();
        }
        return instance;
    }

    public void iniciarmesa() throws IOException{     
        //instancia o jogo
        m_jogo = new Jogo();

        //instancia os quatro jogadores da partida
        m_j0 = new Jogador(0,"Carolina",null);
        m_j0.setHuman();
        m_j1 = new Jogador(1,"Maq 1",null);
        m_j2 = new Jogador(2,"Maq 2",null);
        m_j3 = new Jogador(3,"Maq 3",null);

        //instância o vetor de jogadores
        //e os aloca dentro de um vetor
        m_jogadores = new Jogador[4];
        m_jogadores[0] = m_j0;
        m_jogadores[1] = m_j1;
        m_jogadores[2] = m_j2;
        m_jogadores[3] = m_j3;

        //instancia o vetor de duplas
        //e aloca as duplas
        //as duplas só poderão ser alteradas num novo jogo
        m_D1 = new Jogador[2];
        m_D1[0] = m_j0;
        m_D1[1] = m_j2;
        m_D2 = new Jogador[2];
        m_D2[0] = m_j1;
        m_D2[1] = m_j3;

        //Inicialização da IA
        JogadorIA = new IA();

        //instancia o jogo e o baralho
        m_baralho = new Baralho();
        m_baralho.iniciarBaralho();

        //instancia trunfo
        m_trunfo = new Carta();
    }
    
    public void embaralhar(){        
         m_baralho.embaralhar();
    }

    //distribuição de cartas a ser chamada pelo controlador
    public int distribuirCartas() throws IOException{

        int idTrunfo;
        //opção 0, tira a carta de cima como trunfo,
        //outra opção, tira a de baixo.
        idTrunfo = DistribuirCartas(m_jogadores, getOpcao());

        return idTrunfo;
    }
    
    public void inicializaPartida(){         
         m_partida = new Partida();
    }

    public void inicializaRodada(){
        m_rodada = new Rodada();
    }

    public void setCartasRodada(Carta cartaJogada, int ordem){
        m_rodada.setCartasRodada(cartaJogada, ordem);
    }

    public Carta[] getCartasRodada(){
        return m_rodada.getCartasRodada();
    }

    public Carta[] getCartasPartida(){
        return m_partida.getCartasPartida();
    }

    public void inicializaMaquinaRegras(){
        //instancia máquina de regras
        //a máquina de regras precisa ser instanciada a cada roada
        m_regras = new MaquinaRegra();
    }

    //nesse método 4 jogadores jogam,
    //o parâmetro j é o índice que jogador que irá jogar.
    public boolean jogaRodada(int j, Carta carta) throws IOException{

        boolean valida;
        valida = false;

        //aqui precisa pegar a carta através do id
        
//        if(m_jogadores[j].isHuman()){
//            this.imprimeJogoJogador(m_jogadores[j]);

            //passar na ia
            valida = m_regras.validaJogada(carta, m_jogadores[j].getJogo());
            //senão for válida
            //retorna falso
        if(valida){
            m_rodada.mesaRodada(carta, j);
            m_jogadores[j].jogar(m_jogadores[j], carta);
//        }else{
            //o método escolherCartaJogar já testa se o jogador é humano ou não
            //e toma as atitudes necessárias a cada caso.
            //m_rodada.mesaRodada(escolherCartaJogar(m_jogadores[j]),j);
            // >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> IA FRACA
//            m_rodada.mesaRodada(escolherCartaJogar(m_jogadores[j]),j);
//            m_jogadores[j].jogar(m_jogadores[j],m_rodada.getCarta(j));
//        }
            this.imprimeJogador(m_jogadores[j]);
            this.imprimeCarta(m_rodada.getCarta(j));
            System.out.println(" \n ");
        }
        
        return valida;

    }

    public Jogador venceRodada(){
        // Carta Vencedora
        Carta vencedora;
        vencedora = m_rodada.vencedorRodada(m_trunfo);

        //leva mesa, as cartas da rodada vão para o bolo
        //aqui deve-se saber de qual dupla é a carta vencedora
        m_partida.levaMesa(m_rodada.getCartasRodada(),DuplaVencedora(m_rodada.getCartasRodada(), vencedora));
        this.imprimeDuplasVencedora(DuplaVencedora(m_rodada.getCartasRodada(), vencedora));

        //this.imprimeCartasRodada(m_rodada.getCartasRodada());

        //aqui deve-se reorganizar o vetor de jogadores na ordem correta de jogadores
        Jogador vencedor;
        vencedor = jogadorVencendor(m_rodada.getCartasRodada(), vencedora);
        //this.organizadaOrdemRodada(vencedor, this.getOpcao());
        return vencedor;
    }

    public void salvaRodada(int ordem){
        m_partida.pushRodada(m_rodada, ordem);
    }

    public int vencePartida(){
        int dupla_vencedora;
        dupla_vencedora = m_partida.vencePartida();
        m_jogo.levaPartida(dupla_vencedora, m_partida);
        if(dupla_vencedora == 3){
            String empate = "Empate!!!";
            System.out.println("dupla vencedora da partida: " + empate);
        }
        System.out.println("dupla vencedora da partida: " + dupla_vencedora);
        return dupla_vencedora;
    }

    public void salvaPartida(int index){
        m_jogo.setPartida(m_partida, index);
    }

    public int vencedorJogo(){
        return m_jogo.obterDuplaVencedora();
    }

    public Carta[] getJogoJ0(){
        return m_j0.getJogo();
    }

    public Carta[] getJogoJ1(){
        return m_j1.getJogo();
    }

    public Carta[] getJogoJ2(){
        return m_j2.getJogo();
    }

    public Carta[] getJogoJ3(){
        return m_j3.getJogo();
    }

    public Jogador[] getJogadores(){
        return m_jogadores;
    }

    public IA getIA(){
        return JogadorIA;
    }

    public Baralho getBaralho(){
        return m_baralho;
    }

    public Partida getPartida(){
        return m_partida;
    }

    public Rodada getRodada(){
        return m_rodada;
    }

    public void organizadaOrdemRodada (Jogador jogadorLevouRodada) {

        int opcao = this.getOpcao();

	int id = jogadorLevouRodada.getIdJogador();

        Jogador vencedor;

        vencedor = this.vaiIDvemJogador(id);

	//m_jogadores[0] = vencedor;

        Jogador da_vez;

        Jogador[] jogadores = new Jogador[4];

        jogadores[0] = vencedor;

	if (opcao == 0){
		id++;
		for (int i=1; i < 4; i++) {
			if (id > 3){
				id = 0;
			}
                        da_vez = this.vaiIDvemJogador(id);
			jogadores[i] = da_vez;
			id++;
		}
        }else{
		id--;
		for (int i=1; i < 4; i++) {
			if (id < 0){
				id = 3;
			}
                        da_vez = this.vaiIDvemJogador(id);
			jogadores[i] = da_vez;
			id--;
		}
         }

        for (int i=0; i < 4; i++){
            m_jogadores[i] = jogadores[i];
        }

}

    private Jogador vaiIDvemJogador(int id){

        Jogador vencedor = null;

        for (int i = 0; i < m_jogadores.length; i++){
             if (m_jogadores[i].getIdJogador() == id)
                 vencedor = m_jogadores[i];
        }
        return vencedor;
    }

    private Jogador jogadorVencendor(Carta[] cartasRodada, Carta vencedor){

            int num_jogador = 0;
            for (int j=0; j < cartasRodada.length; j++){
                if (cartasRodada[j].GetId() == vencedor.GetId())
                    num_jogador = j;
            }

            return m_jogadores[num_jogador];
    }


    private int DuplaVencedora(Carta[] cartasRodada, Carta vencedora){

        int num_jog = 0;
        for (int i = 0; i < cartasRodada.length; i++){
            if (vencedora.GetId() == cartasRodada[i].GetId()){
                num_jog = i;
            }
        }

        int idJogador = m_jogadores[num_jog].getIdJogador();

        int dupla_vencedora = 0;

        for (int j = 0; j < m_D1.length; j++){
            if(idJogador == m_D1[j].getIdJogador()){
                dupla_vencedora = 1;
            }
        }

        for (int z = 0; z < m_D2.length; z++){
            if(idJogador == m_D2[z].getIdJogador()){
                dupla_vencedora = 2;
            }
        }

        return dupla_vencedora;
    }

    
    private int DistribuirCartas(Jogador[] jogadores, int opcao){
        
         //opção 0, tira a carta de cima como trunfo,
        //outra opção, tira a de baixo.
        m_trunfo = jogadores[0].escolherTrunfo(m_baralho.getBaralho(), opcao);
        this.imprimeTrunfo();

        //distribuição das cartas de acordo com a opção do jogador
        if (opcao == 0){
            m_baralho.distribuirCartas( 0, jogadores[0]);
            m_baralho.distribuirCartas( 10, jogadores[1]);
            m_baralho.distribuirCartas( 20, jogadores[2]);
            m_baralho.distribuirCartas( 30, jogadores[3]);
        } else {
            m_baralho.distribuirCartas( 30, jogadores[0]);
            m_baralho.distribuirCartas( 0, jogadores[1]);
            m_baralho.distribuirCartas( 10, jogadores[2]);
            m_baralho.distribuirCartas( 20, jogadores[3]);
        }
        return m_trunfo.GetId();
    }

    public void setOpcao(int opcao) throws IOException{
        m_opcao = opcao;
    }

    public int getOpcao(){
        return m_opcao;
    }

    //escolhe a carta a ser jogada por jogador em uma rodada
/*    private Carta escolherCartaJogar(Jogador jog) throws IOException{
         Carta daJogada = null;
         daJogada = new Carta();
         Carta[] maojog = null;
         maojog = jog.getJogo();
        //condição para testar o jogador humano
        //se humano pergunta ao usuário qual carta jogar
        //senão escolhe a carta pela IA
/*        if (jog.isHuman()){
            boolean carta_valida = false;
            while (!carta_valida){
                System.out.println("digite o número da carta a ser jogada.");
                int numCarta;
                InputStreamReader converter = new InputStreamReader(System.in);
                BufferedReader in = new BufferedReader(converter);
                numCarta = Integer.parseInt(in.readLine());
                if(m_regras.validaJogada(maojog[numCarta], maojog)){
                    daJogada = maojog[numCarta];
                    carta_valida = true;
                }
                else{
                    System.out.println("Jogada inválida!");
                }
            }
            
 //       }
//        else{
            boolean carta_valida = false;
            int tamanho_jogo = jog.getJogo().length;
            int i = 0;
            IA jogada = null;
            jogada = IA.getInstance();
            while ((!carta_valida) & (i < tamanho_jogo)){
                Carta aux;
                aux = jogada.escolherJogada(jog);
                if(m_regras.validaJogada(aux, maojog)){
                     daJogada = aux;
                     carta_valida = true;
                }
                i++;
                if (i== (tamanho_jogo - 1)){
                    daJogada = maojog[i];
                }
           }
//        }
        return daJogada;
    }
*/
    /*
    private Carta escolherCartaJogarIAmedia(Jogador jog) throws IOException{
         Carta daJogada = null;
         daJogada = new Carta();
         Carta[] maojog = null;
         maojog = jog.getJogo();
         Carta[] cartasMesa = null;
         cartasMesa = new Carta[40];
         Carta[] cartasRodada = null;
         cartasRodada = new Carta[4];
         int l = 0;
         int j = 0;
        //condição para testar o jogador humano
        //se humano pergunta ao usuário qual carta jogar
        //senão escolhe a carta pela IA
        if (jog.isHuman()){
            boolean carta_valida = false;
            while (!carta_valida){
                System.out.println("digite o número da carta a ser jogada.");
                int numCarta;
                InputStreamReader converter = new InputStreamReader(System.in);
                BufferedReader in = new BufferedReader(converter);
                numCarta = Integer.parseInt(in.readLine());
                if(m_regras.validaJogada(maojog[numCarta], maojog)){
                    daJogada = maojog[numCarta];
                    carta_valida = true;
                    cartasMesa[l] = daJogada;
                    cartasRodada[j] = daJogada;
                    l++;
                    j++;
                }
                else{
                    System.out.println("Jogada inválida!");
                }
            }

        }
        else{
            boolean carta_valida = false;
            int tamanho_jogo = jog.getJogo().length;
            int i = 0;
            IA jogada = null;
            jogada = IA.getInstance();
            while ((!carta_valida) & (i < tamanho_jogo)){
                Carta aux;
                aux = jogada.escolherJogada(jog);
                if(m_regras.validaJogada(aux, maojog)){
                     daJogada = aux;
                     carta_valida = true;
                     cartasMesa[l] = daJogada;
                     cartasRodada[j] = daJogada;
                     l++;
                     j++;
                }
                i++;
                if (i== (tamanho_jogo - 1)){
                    daJogada = maojog[i];
                }
           }
        }
        return daJogada;
    } */
/*
    private Carta escolherCartaJogarIAmedia(Jogador jog) throws IOException{
         Carta daJogada = null;
         daJogada = new Carta();
         Carta[] maojog = null;
         maojog = jog.getJogo();


         //int l = 0;
         //int j = 0;

         if (numCrtsRodada == 4){
             cartasRodada = null;
             numCrtsRodada = 0;
        }

        //condição para testar o jogador humano
        //se humano pergunta ao usuário qual carta jogar
        //senão escolhe a carta pela IA
        if (jog.isHuman()){
            boolean carta_valida = false;
            while (!carta_valida){
                System.out.println("digite o número da carta a ser jogada.");
                int numCarta;
                InputStreamReader converter = new InputStreamReader(System.in);
                BufferedReader in = new BufferedReader(converter);
                numCarta = Integer.parseInt(in.readLine());
                if(m_regras.validaJogada(maojog[numCarta], maojog)){
                    daJogada = maojog[numCarta];
                    carta_valida = true;
                    cartasMesa[numCrtsMesa] = daJogada;
                    cartasRodada[numCrtsRodada] = daJogada;
                    numCrtsMesa++;
                    numCrtsRodada++;
                }
                else{
                    System.out.println("Jogada inválida!");
                }
            }

        }
        else{
            boolean carta_valida = false;
            int tamanho_jogo = jog.getJogo().length;
            int i = 0;
            IA jogada = null;
            jogada = IA.getInstance();
            while ((!carta_valida) & (i < tamanho_jogo)){
                Carta aux;
                aux = jogada.iaMedia(cartasMesa, m_trunfo, jog, cartasRodada);
                if(m_regras.validaJogada(aux, maojog)){
                     daJogada = aux;
                     carta_valida = true;
                     cartasMesa[numCrtsMesa] = daJogada;
                     cartasRodada[numCrtsRodada] = daJogada;
                     numCrtsMesa++;
                     numCrtsRodada++;
                }
                i++;
                if (i== (tamanho_jogo - 1)){
                    daJogada = maojog[i];
                }
           }
        }
        return daJogada;
    }
*/
    private void imprimeCarta(Carta crt){
        System.out.println("jogou a carta: " + crt.GetNome() + " " + crt.GetNaipe());
    }

    private void imprimeTrunfo(){
        //imprime trunfo
        System.out.println("trunfo " + m_trunfo.GetNome() + " " + m_trunfo.GetNaipe() + " ");
        System.out.println();
    }

    private void imprimeCartasRodada(Carta[] cartasRodada){
        System.out.println("Cartas da Rodada: ");
        for(int i = 0; i < cartasRodada.length; i++){
            System.out.println(cartasRodada[i].GetNome() + " " + cartasRodada[i].GetNaipe());
        }
    }

    private void imprimeDuplasVencedora(int dupla){
        System.out.println("Dupla Vencedora: ");
        if (dupla == 1){
            System.out.println("Dupla 1 ");
        }
        else
        {
            System.out.println("Dupla 2 ");
        }
    }

    private void imprimeJogador(Jogador jog){
        System.out.println("O jogador: " + jog.getIdJogador() + " " + jog.getNome());
    }

    private void imprimeJogoJogador(Jogador jog){
        System.out.println(jog.getNome() + " " + jog.getIdJogador());
        Carta maoj0[];
        maoj0 = jog.getJogo();
        int n = maoj0.length;
        for (int i=0; i<n; i++){
            String nome;
            nome = maoj0[i].GetNome();
            String naipe;
            naipe = maoj0[i].GetNaipe();
            int ponto;
            ponto = maoj0[i].GetPonto();
            System.out.println(i + " " + nome + " " + naipe + " " + ponto);
        }
        System.out.println();
    }

    private void imprimeJogoJogadores(){
    //imprime jogadores
        System.out.println(m_j0.getNome() + " " + m_j0.getIdJogador());
        Carta maoj0[];
        maoj0 = m_j0.getJogo();
        int n = 10;
        for (int i=0; i<n; i++){
            String nome;
            nome = maoj0[i].GetNome();
            String naipe;
            naipe = maoj0[i].GetNaipe();
            int ponto;
            ponto = maoj0[i].GetPonto();
            System.out.println(i + " " + nome + " " + naipe + " " + ponto);
        }
        System.out.println();


        System.out.println(m_j1.getNome() + " " + m_j1.getIdJogador());
        Carta maoj1[];
        maoj1 = m_j1.getJogo();
        for (int i=0; i<n; i++){
            String nome;
            nome = maoj1[i].GetNome();
            String naipe;
            naipe = maoj1[i].GetNaipe();
            //System.out.println(i + " " + nome + " " + naipe);
            int ponto;
            ponto = maoj1[i].GetPonto();
            System.out.println(i + " " + nome + " " + naipe + " " + ponto);
        }
        System.out.println();

        System.out.println(m_j2.getNome() + " " + m_j2.getIdJogador());
        Carta maoj2[];
        maoj2 = m_j2.getJogo();
        for (int i=0; i<n; i++){
            String nome;
            nome = maoj2[i].GetNome();
            String naipe;
            naipe = maoj2[i].GetNaipe();
            //System.out.println(i + " " + nome + " " + naipe);
            int ponto;
            ponto = maoj2[i].GetPonto();
            System.out.println(i + " " + nome + " " + naipe + " " + ponto);
        }
        System.out.println();


        System.out.println(m_j3.getNome() + " " + m_j3.getIdJogador());
        Carta maoj3[];
        maoj3 = m_j3.getJogo();
        for (int i=0; i<n; i++){
            String nome;
            nome = maoj3[i].GetNome();
            String naipe;
            naipe = maoj3[i].GetNaipe();
            //System.out.println(i + " " + nome + " " + naipe);
            int ponto;
            ponto = maoj3[i].GetPonto();
            System.out.println(i + " " + nome + " " + naipe + " " + ponto);
        }
        System.out.println();
    }

}
